using Infrastructure.Attribute;
using Infrastructure.Extensions;
using System.Linq.Expressions;
using Infrastructure;
using Microsoft.AspNetCore.Mvc;
using Infrastructure.Filters;
using Mapster;
using ZR.Repository;
using ZR.Service.BaseFrame.IService;
using ZR.Model.BaseFrame.Dto;
using ZR.Model.BaseFrame.Entity;
using ZR.Model.Enums;
using ZR.Model.System.Vo;
using ZR.Model.System;

namespace ZR.Service.BaseFrame.Service
{

    /// <summary>
    /// 模块服务
    /// </summary>
    [AppService(ServiceType = typeof(IModuleService), ServiceLifetime = LifeTime.Scoped)]
    public class ModuleService : ModuleServiceBase, IModuleService
    {
        #region 重写

        /// <summary>
        /// 获取模块树选择列表
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        public override async Task<List<TreeNodeInfo>> GetModuleTreeSelectList(GetModuleTreeSelectListReq req)
        {
            var list = await Repository
                    .WhereIF(req.OnlyLevel1Node, m => m.PaModuleId == 0)
                    .WhereIF(!string.IsNullOrWhiteSpace(req.MenuTypeCode),m=>m.MenuTypeCode==req.MenuTypeCode)
                    .Where(m => m.StateCode != DataStateEnum.Deleted.ToEnumCode())
                    .Select(m => new TreeNodeInfo
                    {
                        Id = m.ModuleId.ToString(),
                        PaId = m.PaModuleId.ToString(),
                        Label = m.ModuleName,
                        Code=m.ModuleCode,
                        Type=m.MenuTypeCode
                    })
                    .ToListAsync();
            if (req.IsReturnRoot)
            {
                list.Add(new TreeNodeInfo
                {
                    Id = "0",
                    Label = string.IsNullOrWhiteSpace(req.RootNodeName) ? "所有模块" : req.RootNodeName,
                    PaId = "-1"
                });
            }
            var treeList = BuildTree(list);
            return treeList;
        }

        #endregion

        #region 新增

        public async Task<List<ModuleEntity>> GetMenuTreeByUserId(long userId)
        {
            var list = await Repository.Context.Queryable<ModuleEntity>()
                .Where(m => m.StateCode == DataStateEnum.Enabled.ToEnumCode())
                .OrderBy(m => new { m.PaModuleId, m.SortNo })
                .ToListAsync();
            list = BuildModuleTree(list);
            return list;
        }

        /// <summary>
        /// 获取路由侧边栏,动态生成
        /// </summary>
        /// <param name="menus"></param>
        /// <param name="paMenu"></param>
        /// <returns></returns>
        public List<RouterVo> BuildMenus(List<ModuleEntity> menus,ModuleEntity paMenu)
        {
            List<RouterVo> routers = new();
            if (menus == null) return routers;

            foreach (var menu in menus)
            {
                MenuTypeEnum menuType;
                var tmpMenuType=menu.MenuType;
                if(tmpMenuType==null)
                {
                    continue;
                }
                menuType = tmpMenuType.Value;
                RouterVo router = new()
                {
                    Query = "",
                    Hidden = !menu.IsVisible,
                    Name = GetRouteName(menu, menuType),
                    Path = GetRoutePath(menu, menuType,paMenu),
                    Component = GetComponent(menu, menuType),
                    Meta = new Meta(menu.ModuleName, menu.Icon, false, menu.ModuleCode, menu.ModuleCode, menu.CreateTime)
                };


                List<ModuleEntity> cMenus = menu.Children;
                //目录菜单，并且有子菜单
                if (menuType == MenuTypeEnum.Catalog && cMenus?.Count > 0)
                {
                    router.AlwaysShow = true;
                    router.Redirect = "noRedirect";
                    router.Children = BuildMenus(cMenus,menu);
                }
                //页面菜单，且是一级菜单
                else if (menuType == MenuTypeEnum.Page && menu.PaModuleId == 0)
                {
                    router.Meta = null;
                    List<RouterVo> childrenList = [];
                    RouterVo children = new()
                    {
                        Query = "",
                        Path = menu.ModuleCode,
                        Component = menu.PagePath,
                        Name = menu.ModuleName.IsNotEmpty() ? menu.ModuleName : menu.ModuleCode.ToLower(),
                        Meta = new Meta(menu.ModuleName, menu.Icon, false, menu.ModuleCode, menu.ModuleCode, menu.CreateTime)
                    };
                    childrenList.Add(children);
                    router.Children = childrenList;
                }
                //外链菜单
                else if (menuType == MenuTypeEnum.OuterLink)
                {
                    router.Meta = new Meta(menu.ModuleName, menu.Icon);
                    router.Path = menu.LinkPath;
                    List<RouterVo> childrenList = new();
                    router.Children = childrenList;
                }
                routers.Add(router);
            }

            return routers;
        }

        #endregion

        #region 构建模块树结构

        /// <summary>
        /// 构建前端所需要树结构
        /// </summary>
        /// <param name="list">列表</param>
        /// <returns></returns>
        private List<ModuleEntity> BuildModuleTree(List<ModuleEntity> list)
        {
            List<ModuleEntity> returnList = new List<ModuleEntity>();
            List<long> allIds = list.Select(f => f.ModuleId).ToList();
            foreach (var dept in list)
            {
                // 如果是顶级节点, 遍历该父节点的所有子节点
                if (!allIds.Contains(dept.PaModuleId))
                {
                    FillChildren(list, dept);
                    returnList.Add(dept);
                }
            }

            if (!returnList.Any())
            {
                returnList = list;
            }
            return returnList;
        }

        /// <summary>
        /// 填充子结点
        /// </summary>
        /// <param name="list"></param>
        /// <param name="t"></param>
        private void FillChildren(List<ModuleEntity> list, ModuleEntity t)
        {
            //得到子节点列表
            List<ModuleEntity> childList = GetChildList(list, t);
            t.Children = childList;
            foreach (var item in childList)
            {
                if (GetChildList(list, item).Count() > 0)
                {
                    FillChildren(list, item);
                }
            }
        }

        /// <summary>
        /// 递归获取子结点
        /// </summary>
        /// <param name="list">所有结点</param>
        /// <param name="item">结点</param>
        /// <returns></returns>
        private List<ModuleEntity> GetChildList(List<ModuleEntity> list, ModuleEntity item)
        {
            return list.Where(p => p.PaModuleId == item.ModuleId).ToList();
        }

        #endregion

        #region 构建菜单

        /// <summary>
        /// 获取路由名称
        /// </summary>
        /// <param name="menu">菜单信息</param>
        /// <param name="menuType">菜单类型</param>
        /// <returns>路由名称</returns>
        private string GetRouteName(ModuleEntity menu, MenuTypeEnum menuType)
        {
            string routerName = menu.ModuleCode.ToLower();
            // 非外链并且是一级目录（类型为目录）
            if (IsMeunFrame(menu, menuType))
            {
                routerName = string.Empty;
            }
            return routerName;
        }

        /// <summary>
        /// 获取路由路径
        /// </summary>
        /// <param name="menu">菜单信息</param>
        /// <param name="menuType">菜单类型</param>
        /// <param name="paMenu">上级菜单</param>
        /// <returns>路由地址</returns>
        private string GetRoutePath(ModuleEntity menu, MenuTypeEnum menuType,ModuleEntity paMenu=null)
        {
            string routerPath = menu.ModuleCode;
            switch (menuType)
            {
                case MenuTypeEnum.Catalog:
                    routerPath = (paMenu?.MenuType==MenuTypeEnum.Catalog?"":"/") + menu.ModuleCode;
                    break;
                case MenuTypeEnum.Page:
                    if (menu.PaModuleId == 0)
                    {
                        routerPath = "/";
                    }
                    break;
                case MenuTypeEnum.OuterLink:
                    routerPath = menu.LinkPath;
                    break;
                default:
                    break;
            }
            return routerPath;
        }

        /// <summary>
        /// 获取组件名称
        /// </summary>
        /// <param name="menu">菜单信息</param>
        /// <param name="menuType">菜单类型</param>
        /// <returns></returns>
        private string GetComponent(ModuleEntity menu, MenuTypeEnum menuType)
        {
            string component = UserConstants.LAYOUT;
            if (!string.IsNullOrEmpty(menu.PagePath) && !IsMeunFrame(menu, menuType))
            {
                component = menu.PagePath?.TrimStart('/');
            }
            else if (menuType == MenuTypeEnum.OuterLink)
            {
                component = UserConstants.OUTER_LINK;
            }
            else if (menuType == MenuTypeEnum.Catalog && menu.PaModuleId != 0)
            {
                component = UserConstants.PARENT_VIEW;
            }
            return component;
        }

        /// <summary>
        /// 是否为菜单内部跳转
        /// </summary>
        /// <param name="menu">菜单信息</param>
        /// <param name="menuType">菜单类型</param>
        /// <returns></returns>
        private bool IsMeunFrame(ModuleEntity menu, MenuTypeEnum menuType)
        {
            return menu.PaModuleId == 0 && menuType == MenuTypeEnum.Page
                ;
        }

        #endregion
    }
}